package com.tzy.spi.core;

import com.tzy.spi.core.cache.CacheBus;
import com.tzy.spi.enhancer.Enhancer;
import com.tzy.spi.exception.LoadClassException;

import java.util.concurrent.ConcurrentHashMap;

public class SpiLoader implements CacheBus {

    private SpiLoader() {

    }


    private static CacheBus bus = new SpiLoader();

    private static final String DEFAULT_PATH = "META-INF/spi/";

    private static final ConcurrentHashMap<Class, SpiBeanHolder> HOLDER_CACHE = new ConcurrentHashMap<Class, SpiBeanHolder>();

    private static ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

    public static void setClassLoader(ClassLoader classLoader) {
        SpiLoader.classLoader = classLoader;
    }

    public static ClassLoader getClassLoader() {
        return SpiLoader.classLoader;
    }

    static {
        //加载所有 增强器bean
        init();
    }

    private static void init() {
        //加载所有 增强器bean
        SpiLoader.loadInterface(Enhancer.class).initAllBeans();
    }

    public static <T> SpiBeanHolder<T> loadInterface(final Class<T> interfaceClass) {

        if (!interfaceClass.isInterface()) {
            throw new LoadClassException(interfaceClass.getName() + " 不是接口，无法加载");
        }

        SpiBeanHolder<T> beanHolder = (SpiBeanHolder<T>) HOLDER_CACHE.get(interfaceClass);

        if (beanHolder == null) {
            HOLDER_CACHE.computeIfAbsent(interfaceClass, (key) -> {


                return new SpiBeanHolder<T>(key, DEFAULT_PATH, classLoader, bus);
            });
            beanHolder = (SpiBeanHolder<T>) HOLDER_CACHE.get(interfaceClass);
        }

        return beanHolder;
    }

    @Override
    public void setToTemp(Class clazz, String key, Object value) {
        SpiBeanHolder holder = HOLDER_CACHE.get(clazz);
        if (holder != null) {
            holder.setToTemp(key, value);
        }

    }

    @Override
    public BeanHolder getHolder(Class clazz, String key) {

        SpiBeanHolder holder = HOLDER_CACHE.get(clazz);
        if (holder != null) {
            return holder.getHolder(key);
        }
        return null;
    }

    @Override
    public InitBeanExecutor getFromInitialBeans(Class clazz, String key) {

        SpiBeanHolder holder = HOLDER_CACHE.get(clazz);
        if (holder != null) {
            return holder.removeFromInitialBeans(key);
        }
        return null;
    }

    @Override
    public Object getFromTempCacheBeans(Class clazz, String key) {

        SpiBeanHolder holder = HOLDER_CACHE.get(clazz);
        if (holder != null) {
            return holder.getFromTemp(key);
        }
        return null;
    }
}
